﻿using Culvert_Help;
using NeXus.BIMBase.Core;
using NeXus.p3d;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Windows.Forms;
using static NeXus.p3d.GeCurveArray;

namespace checc_baseTools
{
    /// <summary>
    /// 跌水井
    /// </summary>
    public class DropWell
    {
        public static BPGraphicsCollection Create(DropWellBase dropWellBase)
        {
            BPProject project = BPApplication.getInstance().getProjectManager().getMainProject();
            BPModelBase model = project.getActiveModel();

            double centerLength = dropWellBase.CenterLength * GeneralHelpers.UOR;// 跌井中心长度
            double deep = dropWellBase.Deep * GeneralHelpers.UOR;// 跌井深度
            double wellSlope = dropWellBase.WellSlope;// 井壁坡度
            double thickness = dropWellBase.Height * GeneralHelpers.UOR;// 井身铺砌厚度
            double depthOfDrainageDitch = dropWellBase.DepthOfDrainageDitch * GeneralHelpers.UOR;// 排水沟深度
            double slope = dropWellBase.Slope;// 跌井边坡坡比(1:n)
            double insideDitchHeight = dropWellBase.InsideDitchHeight * GeneralHelpers.UOR;// 边沟内坡高
            double slopInsideDitch = dropWellBase.SlopInsideDitch;// 边沟内坡度
            double slopOutsideDitch = dropWellBase.SlopOutsideDitch;// 边沟外坡度
            double gutterPavingLength = dropWellBase.GutterPavingLength * GeneralHelpers.UOR;// 排水沟铺砌长
            double precisionPavingHeight = dropWellBase.PrecisionPavingHeight * GeneralHelpers.UOR;// 井底铺砌高度
            double sandPitDepthSwim = dropWellBase.SandPitDepthSwim * GeneralHelpers.UOR;// 沉砂池深度
            double angle = dropWellBase.CulvertAngle - 90;
            double clearSpan = dropWellBase.ClearSpan / Math.Cos(Math.PI * angle / 180) * GeneralHelpers.UOR;
            #region 底部矩形
            //底部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection bot = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - thickness, -sandPitDepthSwim - precisionPavingHeight),
                new GePoint3d(centerLength, -clearSpan / 2 - thickness, -sandPitDepthSwim - precisionPavingHeight),
                new GePoint3d(centerLength, clearSpan / 2 + thickness, -sandPitDepthSwim - precisionPavingHeight),
                new GePoint3d(0, clearSpan / 2 + thickness, -sandPitDepthSwim - precisionPavingHeight),
            };

            //顶部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection top = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - thickness, -sandPitDepthSwim),
                new GePoint3d(centerLength, -clearSpan / 2 - thickness, -sandPitDepthSwim),
                new GePoint3d(centerLength, clearSpan / 2 + thickness, -sandPitDepthSwim),
                new GePoint3d(0, clearSpan / 2 + thickness, -sandPitDepthSwim),
            };

            GeCurveArray curveBot = GeCurveArray.createLinestringArray(bot, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveTop = GeCurveArray.createLinestringArray(top, BoundaryType.BOUNDARY_TYPE_Outer, true);
            //扫掠成体
            IGeSolidBase botton = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveTop, curveBot, true));
            #endregion

            #region 三侧边墙
            //外部边缘！！！
            //两侧边坡宽 深度 * 坡度
            double sideWidth = deep * slope;
            //两侧边坡厚度斜边长度
            double sideAngle = Math.Atan2(deep, sideWidth);
            double sideLength = thickness / Math.Sin(sideAngle);

            //正面边坡宽 
            double frontWidth = deep * wellSlope;
            //井壁厚度斜边长度
            double frontAngle = Math.Atan2(deep, frontWidth);

            double frontLength = thickness / Math.Sin(frontAngle);
            GePoint3d gePoint3d1 = GePoint3d.createByZero();
            GePoint3d gePoint3d2 = GePoint3d.createByZero();
            if (wellSlope >= 1)
            {
                gePoint3d1 = new GePoint3d(centerLength, -clearSpan / 2 - thickness, -sandPitDepthSwim - frontLength);
                gePoint3d2 = new GePoint3d(centerLength, clearSpan / 2 + thickness, -sandPitDepthSwim - frontLength);
            }
            //else if (wellSlope > 1)
            //{
            //    gePoint3d1 = new GePoint3d(centerLength, -clearSpan / 2 - thickness, -sandPitDepthSwim - frontLength);
            //    gePoint3d2 = new GePoint3d(centerLength, clearSpan / 2 + thickness, -sandPitDepthSwim - frontLength);
            //}
            else
            {
                gePoint3d1 = new GePoint3d(centerLength + frontLength / 2, -clearSpan / 2 - thickness, -sandPitDepthSwim - frontLength);
                gePoint3d2 = new GePoint3d(centerLength + frontLength / 2, clearSpan / 2 + thickness, -sandPitDepthSwim - frontLength);
            }
            //底部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection outerBot = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - thickness, -sandPitDepthSwim - frontLength),
                gePoint3d1,
                gePoint3d2,
                new GePoint3d(0, clearSpan / 2 + thickness, -sandPitDepthSwim - frontLength),
            };

            //顶部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection outerTop = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(0, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep)
            };

            GeCurveArray curveOuterBot = GeCurveArray.createLinestringArray(outerBot, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveOuterTop = GeCurveArray.createLinestringArray(outerTop, BoundaryType.BOUNDARY_TYPE_Outer, true);
            //扫掠成体
            IGeSolidBase outer = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveOuterTop, curveOuterBot, true));
            BPGraphics outerGraphic = Element_solid.BoolCollection(botton, outer, false);

            //内部剪切体！！！
            //底部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection insideBotton = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2, -sandPitDepthSwim),
                new GePoint3d(centerLength, -clearSpan / 2, -sandPitDepthSwim),
                new GePoint3d(centerLength, clearSpan / 2, -sandPitDepthSwim),
                new GePoint3d(0, clearSpan / 2, -sandPitDepthSwim),
            };

            //顶部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection insideTop = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth,-sandPitDepthSwim + deep),//顶面Z值乘2 保证井口能被裁剪出来
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth, -sandPitDepthSwim + deep),
                new GePoint3d(0, clearSpan / 2 + sideWidth, -sandPitDepthSwim + deep)
            };
            //内部剪切体 点成面 面成体
            GeCurveArray curveInsideBot = GeCurveArray.createLinestringArray(insideBotton, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveInsideTop = GeCurveArray.createLinestringArray(insideTop, BoundaryType.BOUNDARY_TYPE_Outer, true);
            //扫掠成体
            IGeSolidBase inside = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveInsideBot, curveInsideTop, true));
            //布尔差集
            outerGraphic = Element_solid.BoolDifferenceSet(outerGraphic, inside, false);
            #endregion

            #region 内外边坡！！
            //内边坡！！
            //内边坡长 高度 * 坡比
            double innerSlopeLength = insideDitchHeight * slopInsideDitch;
            //井壁厚度斜边长度
            double innerSlopeWidth = insideDitchHeight * slope;
            //右侧三点（近洞口下 远洞口下 近洞口上）
            GePoint3dCollection innerSlopeRight = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(innerSlopeLength, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(0, -clearSpan / 2 - sideWidth - sideLength - innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
            };

            //左侧三点（近洞口下 远洞口下 近洞口上）
            GePoint3dCollection innerSlopeLeft = new GePoint3dCollection()
            {
                new GePoint3d(0, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(innerSlopeLength, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(0, clearSpan / 2 + sideWidth + sideLength + innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
            };
            //内边坡被剪切体 点成面 面成体
            GeCurveArray curveInnerSlopeRight = GeCurveArray.createLinestringArray(innerSlopeRight, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveInnerSlopeLeft = GeCurveArray.createLinestringArray(innerSlopeLeft, BoundaryType.BOUNDARY_TYPE_Inner, true);
            //扫掠成体
            IGeSolidBase innerSlope = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveInnerSlopeLeft, curveInnerSlopeRight, true));

            //外边坡！！！
            //外边坡长 排水沟高度 * 坡比
            double outerSlopeLength = depthOfDrainageDitch * slopOutsideDitch;
            //井壁厚度斜边长度
            double outerSlopeWidth = depthOfDrainageDitch * slope;
            //右侧三点（近洞口下 远洞口下 远洞口上）
            GePoint3dCollection outerSlopeRight = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth - outerSlopeLength, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength - outerSlopeWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };
            //左侧三点（近洞口下 远洞口下 远洞口上）
            GePoint3dCollection outerSlopeLeft = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth - outerSlopeLength, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength + outerSlopeWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };
            //内边坡被剪切体 点成面 面成体
            GeCurveArray curveOuterSlopeRight = GeCurveArray.createLinestringArray(outerSlopeRight, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveOuterSlopeLeft = GeCurveArray.createLinestringArray(outerSlopeLeft, BoundaryType.BOUNDARY_TYPE_Inner, true);
            //扫掠成体
            IGeSolidBase outerSlope = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveOuterSlopeRight, curveOuterSlopeLeft, true));
            //（内外边坡）布尔合集
            BPGraphics innerOuterSlopes = Element_solid.BoolCollection(innerSlope, outerSlope, false);

            //内外边坡裁剪体
            //底部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection SlopeBot = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth, -sandPitDepthSwim + deep),
                new GePoint3d(0, clearSpan / 2 + sideWidth, -sandPitDepthSwim + deep)
            };

            //顶部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection SlopeTop = new GePoint3dCollection()
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth - innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - outerSlopeWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + outerSlopeWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(0, clearSpan / 2 + sideWidth + innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
            };
            //内部剪切体 点成面 面成体
            GeCurveArray curveSlopeBot = GeCurveArray.createLinestringArray(SlopeBot, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveSlopeTop = GeCurveArray.createLinestringArray(SlopeTop, BoundaryType.BOUNDARY_TYPE_Outer, true);
            //扫掠成体
            IGeSolidBase splicedForm = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveSlopeBot, curveSlopeTop, true));

            //布尔叉集裁剪内外边坡
            innerOuterSlopes = Element_solid.BoolDifferenceSet(innerOuterSlopes, splicedForm, false);

            #endregion

            #region 两侧排水沟
            //排水沟厚度斜边长度
            double drainageDitchWidth = depthOfDrainageDitch * slope;
            //右侧四点（近洞口下 远洞口下 远洞口上 近洞口上）
            GePoint3dCollection drainageDitchRight = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength - drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength - drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };

            //左侧四点（近洞口下 远洞口下 远洞口上 近洞口上）
            GePoint3dCollection drainageDitchLeft = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength + drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength + drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };
            //内边坡被剪切体 点成面 面成体
            GeCurveArray curveDrainageDitchRight = GeCurveArray.createLinestringArray(drainageDitchRight, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveDrainageDitchLeft = GeCurveArray.createLinestringArray(drainageDitchLeft, BoundaryType.BOUNDARY_TYPE_Inner, true);
            //扫掠成体
            IGeSolidBase drainageDitch = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveDrainageDitchRight, curveDrainageDitchLeft, true));

            //剪切体
            //右侧四点（近洞口下 远洞口下 远洞口上 近洞口上）
            GePoint3dCollection innerDrainageDitchRight = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength - drainageDitchWidth + sideLength, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength - drainageDitchWidth + sideLength, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };

            //左侧四点（近洞口下 远洞口下 远洞口上 近洞口上）
            GePoint3dCollection innerDrainageDitchLeft = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength + drainageDitchWidth - sideLength, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength + drainageDitchWidth - sideLength, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };
            //内边坡被剪切体 点成面 面成体
            GeCurveArray curveInnerDrainageDitchRight = GeCurveArray.createLinestringArray(innerDrainageDitchRight, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curveInnerDrainageDitchLeft = GeCurveArray.createLinestringArray(innerDrainageDitchLeft, BoundaryType.BOUNDARY_TYPE_Inner, true);
            //扫掠成体
            IGeSolidBase InnerdrainageDitch = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curveInnerDrainageDitchRight, curveInnerDrainageDitchLeft, true));
            //布尔叉集裁剪两侧排水沟
            BPGraphics drainageDitchGraphics = Element_solid.BoolDifferenceSet(drainageDitch, InnerdrainageDitch, false);
            #endregion

            #region 铺砌加长！
            //顶部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection paveTop = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength, -sandPitDepthSwim + deep),
            };
            //铺砌底距井底高度的坡比宽度
            double width = (thickness - 0.08 * GeneralHelpers.UOR) * slope;

            //底部四点（洞口出口方向 近洞头右 远洞口右 远洞口左 近洞口左）
            GePoint3dCollection paveBot = new GePoint3dCollection()
            {
                new GePoint3d(centerLength + frontWidth, -clearSpan / 2 - sideWidth - sideLength + width, -sandPitDepthSwim + deep - thickness),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength+ width, -sandPitDepthSwim + deep - thickness),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength- width, -sandPitDepthSwim + deep - thickness),
                new GePoint3d(centerLength + frontWidth, clearSpan / 2 + sideWidth + sideLength- width, -sandPitDepthSwim + deep - thickness),
            };
            //内部剪切体 点成面 面成体
            GeCurveArray curvePaveBot = GeCurveArray.createLinestringArray(paveBot, BoundaryType.BOUNDARY_TYPE_Outer, true);
            GeCurveArray curvePaveTop = GeCurveArray.createLinestringArray(paveTop, BoundaryType.BOUNDARY_TYPE_Outer, true);
            //扫掠成体
            IGeSolidBase pave = IGeSolidBase.createGeRuledSweep(new GeRuledSweepInfo(curvePaveBot, curvePaveTop, true));
            #endregion

            //布尔合集
            outerGraphic = Element_solid.BoolCollection(outerGraphic, pave, false);//底部 三侧边墙 铺砌
            BPGraphics bPGraphics = Element_solid.BoolCollection(innerOuterSlopes, drainageDitchGraphics, false);//内外边坡 排水墙
            BPGraphics all = Element_solid.BoolCollection(outerGraphic, bPGraphics, false);//内外边坡 排水墙

            //旋转洞口角度
            all = Helper.unitRotation(all, -angle);
            //返回跌水井顶面四个点的平面
            GePoint3dCollection planPoint3D = new GePoint3dCollection
            {
                new GePoint3d(0, -clearSpan / 2 - sideWidth - sideLength - innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
                new GePoint3d(0, clearSpan / 2 + sideWidth + sideLength + innerSlopeWidth, -sandPitDepthSwim + deep + insideDitchHeight),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, clearSpan / 2 + sideWidth + sideLength + drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
                new GePoint3d(centerLength + frontWidth + frontLength + gutterPavingLength, -clearSpan / 2 - sideWidth - sideLength - drainageDitchWidth, -sandPitDepthSwim + deep + depthOfDrainageDitch),
            };
            GeCurveArray geCurveArray = GeCurveArray.createLinestringArray(planPoint3D, BoundaryType.BOUNDARY_TYPE_Outer, true);
            BPGraphics plan = GeneralHelpers.Model2D.createPhysicalGraphics();
            plan.addCurveArray(geCurveArray);
            plan = Helper.unitRotation(plan, -angle);
            return new BPGraphicsCollection { all, plan };
        }
    }
}
